﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace ToolKit.Mvvm.Bindings
{
    public class ObservableObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler? PropertyChanged;
        protected void OnPropertyChanged([CallerMemberName] string? propertyName = null)
        {
            OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }

        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            ArgumentNullException.ThrowIfNull(e, "e");
            this.PropertyChanged?.Invoke(this, e);
        }

        protected bool SetProperty<T>([System.Diagnostics.CodeAnalysis.NotNullIfNotNull("newValue")] ref T field, T newValue, [CallerMemberName] string? propertyName = null)
        {
            /* 自定义实现两个对象的相等比较
             * object.Equals方法是面向Object类型的，如果用于泛型对象，在判断是否相等的过程需要进行大量的装箱/拆箱操作，
             * 尤其是复合类型，由于要进行细致的比较，类型转换更为频繁，这样会带来一定量的性能开销，所以，对于泛型集合
             * 的相等比较，应该考虑使用 IEqualityComparer<T>，Dotnet类型提供了一个实现了该接口的抽象类——EqualityComparer<T>。
             * 
             * 在实际使用中，不妨直接实现这个抽象类，好处是该抽象类公开了一个静态的Default属性，可以返回平台默认的比较方案。
             * 因此，实现该抽象类的好处在于，既可以提供自定义实现，同时也可以保留默认行为。
             */
            if (EqualityComparer<T>.Default.Equals(field, newValue))
            {
                return false;
            }

            field = newValue;
            OnPropertyChanged(propertyName);
            return true;
        }
    }
}
